package cn.wolfcode.wolf2w.controller;

import cn.wolfcode.wolf2w.domain.Destination;
import cn.wolfcode.wolf2w.domain.Strategy;
import cn.wolfcode.wolf2w.domain.Travel;
import cn.wolfcode.wolf2w.domain.UserInfo;
import cn.wolfcode.wolf2w.elasticsearch.domain.DestinationEs;
import cn.wolfcode.wolf2w.elasticsearch.domain.StrategyEs;
import cn.wolfcode.wolf2w.elasticsearch.domain.TravelEs;
import cn.wolfcode.wolf2w.elasticsearch.domain.UserInfoEs;
import cn.wolfcode.wolf2w.elasticsearch.query.SearchObjectQuery;
import cn.wolfcode.wolf2w.elasticsearch.service.ISearchService;
import cn.wolfcode.wolf2w.elasticsearch.vo.SearchResultVO;
import cn.wolfcode.wolf2w.service.IDestinationService;
import cn.wolfcode.wolf2w.service.IStrategyService;
import cn.wolfcode.wolf2w.service.ITravelService;
import cn.wolfcode.wolf2w.service.IUserInfoService;
import cn.wolfcode.wolf2w.util.JsonResult;
import cn.wolfcode.wolf2w.util.ParamMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;

@RestController
public class SearchController {
    // es
    @Autowired
    private ISearchService searchService;

    // mongodb
    @Autowired
    private IStrategyService strategyService;
    @Autowired
    private ITravelService travelService;
    @Autowired
    private IUserInfoService userInfoService;
    @Autowired
    private IDestinationService destinationService;


    @GetMapping("/q")
    public Object search(SearchObjectQuery qo) throws UnsupportedEncodingException {
        //通过解析出成中文（编码）
        qo.setKeyword(URLDecoder.decode(qo.getKeyword(), "UTF-8"));

        switch (qo.getType()){
            case SearchObjectQuery.TYPE_DEST:
                return this.searchDest(qo);
            case SearchObjectQuery.TYPE_STRA:
                return this.searchStrategy(qo);
            case SearchObjectQuery.TYPE_TRAL:
                return this.searchTravel(qo);
            case SearchObjectQuery.TYPE_USER:
                return this.searchUser(qo);
            default:
                return this.searchAll(qo);
        }
    }

    private Object searchDest(SearchObjectQuery qo){
        // 不必要用es搜索，用MongoDB搜索即可。（精准查询） 因为es查询数据，导入头像没了， 使用es使用mongodb去查询
        Destination destination =   destinationService.queryByName(qo.getKeyword());

        // 判断目的地是否存在，不存在，返回空
        SearchResultVO vo = new SearchResultVO();
        if (destination != null){
            // result:  total strategys  travels  users
            List<Strategy> strategies = strategyService.findByDestName(qo.getKeyword());
            List<Travel> travels = travelService.findByDestName(qo.getKeyword());
            for (Travel travel : travels) {
                travel.setAuthor(userInfoService.get(travel.getUserId()));
            }
            List<UserInfo> userInfos = userInfoService.findByCity(qo.getKeyword());
            vo.setStrategys(strategies);
            vo.setTotal(strategies.size() + travels.size() + userInfos.size() + 0L);
            vo.setTravels(travels);
            vo.setUsers(userInfos);
            // qo
            // dest
        }
        return JsonResult.success(ParamMap.newInstance().put("result",vo).put("dest",destination).put("qo",qo));
    }

    private Object searchStrategy(SearchObjectQuery qo){
        // 全文搜索 + 高亮显示
        // page
        // qo
        return JsonResult.success(ParamMap.newInstance().put("page",this.searchStrategyWithHighlight(qo)).put("qo",qo));
    }

    private Object searchTravel(SearchObjectQuery qo){
        // 全文搜索 + 高亮显示
        // page
        // qo
        return JsonResult.success(ParamMap.newInstance().put("page",this.searchTravelWithHighlight(qo)).put("qo",qo));
    }

    private Object searchUser(SearchObjectQuery qo){
        // 全文搜索 + 高亮显示
        // page
        // qo
        return JsonResult.success(ParamMap.newInstance().put("page",this.searchUserWithHighlight(qo)).put("qo",qo));
    }

    private Object searchAll(SearchObjectQuery qo){
        // result:  total strategys  travels  users dest
        // qo
        return JsonResult.success(ParamMap.newInstance().put("result",this.searchAllWithHighlight(qo)).put("qo",qo));
    }


    private Page<Strategy> searchStrategyWithHighlight(SearchObjectQuery qo){
        return searchService.searchWithHighlight(StrategyEs.INDEX_NAME,StrategyEs.TYPE_NAME,Strategy.class,qo,"title","subTitle","summary");
    }
    private Page<Travel> searchTravelWithHighlight(SearchObjectQuery qo){
        return searchService.searchWithHighlight(TravelEs.INDEX_NAME,TravelEs.TYPE_NAME,Travel.class,qo,"title","summary");
    }
    private Page<UserInfo> searchUserWithHighlight(SearchObjectQuery qo){
        return searchService.searchWithHighlight(UserInfoEs.INDEX_NAME,UserInfoEs.TYPE_NAME,UserInfo.class,qo,"nickname","city","info");
    }
    private Page<Destination> searchDestWithHighlight(SearchObjectQuery qo){
        return searchService.searchWithHighlight(DestinationEs.INDEX_NAME,DestinationEs.TYPE_NAME,Destination.class,qo,"name","info");
    }

    private SearchResultVO searchAllWithHighlight(SearchObjectQuery qo){
        SearchResultVO vo = new SearchResultVO();
        Page<Strategy> strategy = this.searchStrategyWithHighlight(qo);
        Page<Travel> travel = this.searchTravelWithHighlight(qo);
        for (Travel tra : travel) {
            tra.setAuthor(userInfoService.get(tra.getUserId()));
        }
        Page<UserInfo> userInfo = this.searchUserWithHighlight(qo);
        Page<Destination> destination = this.searchDestWithHighlight(qo);

        vo.setUsers(userInfo.getContent());  // 转为list
        vo.setTravels(travel.getContent());
        vo.setStrategys(strategy.getContent());
        vo.setDests(destination.getContent());

        vo.setTotal(strategy.getTotalElements() + travel.getTotalElements() + userInfo.getTotalElements() + destination.getTotalElements());

        return vo;
    }
}
